'''
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http:#www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
'''
from base.rdf.RDFNode import RDFNode

#import org.apache.jena.datatypes.RDFDatatype;
#import org.apache.jena.shared.PropertyNotFoundException;


'''
 * An RDF Resource.
 * <p>
 * Resource instances when created may be associated with a specific model.
 * Resources created <i>by</i> a model will refer to that model, and support
 * a range of methods, such as <code>getProperty()</code> and
 * <code>addProperty()</code> which will access or modify that model.  This
 * enables the programmer to write code in a compact and easy style.
 *
 * <p>
 * Resources created by ResourceFactory will not refer to any model, and will
 * not permit operations which require a model. Such resources are useful
 * as general constants.
 *
 * <p>This interface provides methods supporting typed literals.  This means
 * that methods are provided which will translate a built in type, or an
 * object to an RDF Literal.  This translation is done by invoking the
 * <CODE>toString()</CODE> method of the object, or its built in equivalent.
 * The reverse translation is also supported.  This is built in for built
 * in types.  Factory objects, provided by the application, are used
 * for application objects.</p>
 * <p>This interface provides methods for supporting enhanced resources.  An
 * enhanced resource is a resource to which the application has added
 * behaviour.  RDF containers are examples of enhanced resources built in
 * to this package.  Enhanced resources are supported by encapsulating a
 * resource created by an implementation in another class which adds
 * the extra behaviour.  Factory objects are used to construct such
 * enhanced resources.</p>
'''
from abc import ABC, abstractmethod

class Resource(RDFNode):

    '''
     * Returns an a unique identifier for anonymous resources.
     *
     * <p>The id is unique within the scope of a particular implementation.  All
     * models within an implementation will use the same id for the same anonymous
     * resource.</p>
     *
     * <p>This method is undefined if called on resources which are not anonymous
     * and may raise an exception.</p>
     *
     * @return A unique id for an anonymous resource.
    '''
    # param 
    # result AnonId
    @abstractmethod
    def getId(self):
        pass

    '''
     * Override RDFNode.inModel() to produce a statically-typed Resource
     * in the given Model.
    '''
    #@Override
    # param Model m
    # result Resource
    @abstractmethod
    def inModel(self, m):
        pass

    '''
     * Answer true iff this Resource is a URI resource with the given URI.
     * Using this is preferred to using getURI() and .equals().
    '''
    # param String uri
    # result boolean
    @abstractmethod
    def hasURI(self, uri):
        pass

    '''
     * Return the URI of the resource, or null if it's a bnode or statement.
     *
     * @return The URI of the resource, or null if it's a bnode or statement.
    '''
    # param 
    # result String
    @abstractmethod
    def getURI(self):
        pass

    '''
     * Return the statement of this resource, or null if it is not an RDF-star triple term.
     * This is not a resource for a reified statement.
     *
     * @return The statement of this resource,or null if it is not an RDF-star triple term.
    '''
    # param 
    # result Statement
    @abstractmethod
    def getStmtTerm(self):
        pass

    '''
     * Returns the namespace associated with this resource if it is a URI, else return null.
     * <p>
     * The namespace is suitable for use with localname in in RDF/XML.
     * XML does not allow QNames to start with a digit and this method
     * reflects that restriction in the values for namespace and localname.
     * <p>
     * See functions in:@code SplitIRI for other split algorithms.
     *
     * @return The namespace for this resource or null.
    '''
    # param 
    # result String
    @abstractmethod
    def getNameSpace(self):
        pass

    '''
     * Returns the localname of this resource within its namespace if it is a URI else null.
     * <p>
     * Note: XML requires QNames to start with a letter, not a digit,
     * and this method reflects that restriction.
     * <p>
     * See functions in:@code SplitIRI for other split algorithms.
     *
     * @return The localname of this property within its namespace.
    '''
    # param 
    # result String
    @abstractmethod
    def getLocalName(self):
        pass

    '''
     * Return a string representation of the resource.
     * <p>
     * Returns the URI of the resource unless the resource is anonymous
     * in which case it returns the id of the resource enclosed in square
     * brackets.
     *
     * @return Return a string representation of the resource.
     * if it is anonymous.
    '''
    #@Override
    # param 
    # result String
    @abstractmethod
    def toString(self):
        pass

    '''
     * Determine whether two objects represent the same resource.
     *
     * <p>A resource can only be equal to another resource.
     * If both resources are not anonymous, then they are equal if the URI's are
     * equal.  If both resources are anonymous, they are equal only if their Id's
     * are the same.  If one resource is anonymous and the other is not, then they
     * are not equal.</p>
     *
     * @param o The object to be compared.
     * @return true if and only if both objects are equal
    '''
    #@Override
    # param Object o
    # result boolean
    @abstractmethod
    def equals(self, o):
        pass

    '''
     * Get a property value of this resource.
     *
     * <p>The model associated with the resource instance is searched for statements
     * whose subject is this resource and whose predicate is p.  If such a statement
     * is found, it is returned.  If several such statements are found, any one may
     * be returned.  If no such statements are found, an exception is thrown.</p>
     *
     * @param p The property sought.
     * @return some (this, p, ?O) statement if one exists
     * @throws PropertyNotFoundException if no such statement found
    '''
    # param Property p
    # result Statement
    # @abstractmethod
    # def getRequiredProperty(self, p):
    #     pass

    '''
     * Get a property value of this resource in a specified language.
     *
     * <p>The model associated with the resource instance is searched for statements
     * whose subject is this resource and whose predicate is p.  If such a statement
     * is found, it is returned.  If several such statements are found, any one may
     * be returned.  If no such statements are found, an exception is thrown.</p>
     *
     * @param p    The property sought.
     * @param lang The language of the statement with the property sought.
     * @return some (this, p, ?O@lang) statement if one exists
     * @throws PropertyNotFoundException if no such statement found
    '''
    # param Property p, String lang
    # result Statement
    @abstractmethod
    def getRequiredProperty(self, p, lang):
        pass

    '''
     * Answer some statement (this, p, O) in the associated model. If there are several
     * such statements, any one of them may be returned. If no such statements exist,
     * null is returned - in this is differs from getRequiredProperty.
     *
     * @param p the property sought
     * @return a statement (this, p, O), or null if no such statements exist here
    '''
    # param Property p
    # result Statement
    # @abstractmethod
    # def getProperty(self, p):
    #     pass

    '''
     * Answer some statement (this, p, O), in language <code>lang</code>, in the
     * associated model. If there are several such statements, any one of them may be
     * returned. If no such statements exist, null is returned - in this it differs
     * from getRequiredProperty.
     *
     * @param p    The property sought.
     * @param lang The language of the property sought.
     * @return some (this, p, ?O@lang) statement if one exists
    '''
    # param Property p, String lang
    # result Statement
    @abstractmethod
    def getProperty(self, p, lang):
        pass

    '''
     * List all the values of the property p.
     *
     * <p>Returns an iterator over all the statements in the associated model whose
     * subject is this resource and whose predicate is p.</p>
     *
     * @param p The predicate sought.
     * @return An iterator over the statements.
    '''
    # param Property p
    # result StmtIterator
    # @abstractmethod
    # def listProperties(self, p):
    #     pass

    '''
     * Return an iterator over all the properties of this resource with a specific language.
     *
     * <p>The model associated with this resource is searched and an iterator is
     * returned which iterates over all the statements which have this resource
     * as a subject.</p>
     *
     * @return An iterator over all the statements about this object.
    '''
    # param Property p, String lang
    # result StmtIterator
    @abstractmethod
    def listProperties(self, p, lang):
        pass


    '''
     * Return an iterator over all the properties of this resource.
     *
     * <p>The model associated with this resource is search and an iterator is
     * returned which iterates over all the statements which have this resource
     * as a subject.</p>
     *
     * @return An iterator over all the statements about this object.
    '''
    # param 
    # result StmtIterator
    # @abstractmethod
    # def listProperties(self):
    #     pass

    '''
     * Add the property <code>p</code> with the typed-literal value <code>o</code>
     * to this resource, <i>ie</i> add (this, p, typed(o)) to this's model. Answer
     * this resource. The typed literal is equal to one constructed by using
     * <code>this.getModel().createTypedLiteral(o)</code>.
    '''
    # param Property p, boolean o
    # result Resource
    @abstractmethod
    def addLiteral(self, p, o):
        pass

    '''
     * Add the property <code>p</code> with the typed-literal value <code>o</code>
     * to this resource, <i>ie</i> add (this, p, typed(o)) to this's model. Answer
     * this resource. The typed literal is equal to one constructed by using
     * <code>this.getModel().createTypedLiteral(o)</code>.
    '''
    # param Property p, long o
    # result Resource
    # @abstractmethod
    # def addLiteral(self, p, o):
    #     pass

    '''
     * Add the property <code>p</code> with the typed-literal value <code>o</code>
     * to this resource, <i>ie</i> add (this, p, typed(o)) to this's model. Answer
     * this resource. The typed literal is equal to one constructed by using
     * <code>this.getModel().createTypedLiteral(o)</code>.
    '''
    # param Property p, char o
    # result Resource
    # @abstractmethod
    # def addLiteral(self, p, o):
    #     pass

    '''
     * Add the property <code>p</code> with the typed-literal value <code>o</code>
     * to this resource, <i>ie</i> add (this, p, typed(o)) to this's model. Answer
     * this resource. The typed literal is equal to one constructed by using
     * <code>this.getModel().createTypedLiteral(o)</code>.
    '''
    # param Property value, double d
    # result Resource
    # @abstractmethod
    # def addLiteral(self, value, d):
    #     pass

    '''
     * Add the property <code>p</code> with the typed-literal value <code>o</code>
     * to this resource, <i>ie</i> add (this, p, typed(o)) to this's model. Answer
     * this resource. The typed literal is equal to one constructed by using
     * <code>this.getModel().createTypedLiteral(o)</code>.
    '''
    # param Property value, float d
    # result Resource
    # @abstractmethod
    # def addLiteral(self, value, d):
    #     pass

    '''
     * Add the property <code>p</code> with the typed-literal value <code>o</code>
     * to this resource, <i>ie</i> add (this, p, typed(o)) to this's model. Answer
     * this resource. The typed literal is equal to one constructed by using
     * <code>this.getModel().createTypedLiteral(o)</code>.
    '''
    # param Property p, Object o
    # result Resource
    # @abstractmethod
    # def addLiteral(self, p, o):
    #     pass

    '''
     * Add the property <code>p</code> with the pre-constructed Literal value
     * <code>o</code> to this resource, <i>ie</i> add (this, p, o) to this's
     * model. Answer this resource. <b>NOTE</b> thjat this is distinct from the
     * other addLiteral methods in that the Literal is not turned into a Literal.
    '''
    # param Property p, Literal o
    # result Resource
    # @abstractmethod
    # def addLiteral(self, p, o):
    #     pass

    '''
     * Add a property to this resource.
     *
     * <p>A statement with this resource as the subject, p as the predicate and o
     * as the object is added to the model associated with this resource.</p>
     *
     * @param p The property to be added.
     * @param o The value of the property to be added.
     * @return This resource to allow cascading calls.
    '''
    # param Property p, String o
    # result Resource
    # @abstractmethod
    # def addProperty(self, p, o):
    #     pass

    '''
     * Add a property to this resource.
     *
     * <p>A statement with this resource as the subject, p as the predicate and o
     * as the object is added to the model associated with this resource.</p>
     *
     * @param p The property to be added.
     * @param o The value of the property to be added.
     * @param l the language of the property
     * @return This resource to allow cascading calls.
    '''
    # param Property p, String o, String l
    # result Resource
    @abstractmethod
    def addProperty(self, p, o, l):
        pass

    '''
     * Add a property to this resource.
     *
     * <p>A statement with this resource as the subject, p as the predicate and o
     * as the object is added to the model associated with this resource.</p>
     *
     * @param p           The property to be added.
     * @param lexicalForm The lexical form of the literal
     * @param datatype    The datatype
     * @return This resource to allow cascading calls.
    '''
    # param Property p, String lexicalForm, RDFDatatype datatype
    # result Resource
    # @abstractmethod
    # def addProperty(self, p, lexicalForm, datatype):
    #     pass

    '''
     * Add a property to this resource.
     *
     * <p>A statement with this resource as the subject, p as the predicate and o
     * as the object is added to the model associated with this resource.</p>
     *
     * @param p The property to be added.
     * @param o The value of the property to be added.
     * @return This resource to allow cascading calls.
    '''
    # param Property p, RDFNode o
    # result Resource
    # @abstractmethod
    # def addProperty(self, p, o):
    #     pass

    '''
     * Determine whether this resource has any values for a given property.
     *
     * @param p The property sought.
     * @return true if and only if this resource has at least one
     * value for the property.
    '''
    # param Property p
    # result boolean
    @abstractmethod
    def hasProperty(self, p):
        pass

    '''
     * Answer true iff this resource has the value <code>o</code> for
     * property <code>p</code>. <code>o</code> is interpreted as
     * a typed literal with the appropriate RDF type.
    '''
    # param Property p, boolean o
    # result boolean
    @abstractmethod
    def hasLiteral(self, p, o):
        pass

    '''
     * Answer true iff this resource has the value <code>o</code> for
     * property <code>p</code>. <code>o</code> is interpreted as
     * a typed literal with the appropriate RDF type.
    '''
    # param Property p, long o
    # result boolean
    # @abstractmethod
    # def hasLiteral(self, p, o):
    #     pass

    '''
     * Answer true iff this resource has the value <code>o</code> for
     * property <code>p</code>. <code>o</code> is interpreted as
     * a typed literal with the appropriate RDF type.
    '''
    # param Property p, char o
    # result boolean
    # @abstractmethod
    # def hasLiteral(self, p, o):
    #     pass

    '''
     * Answer true iff this resource has the value <code>o</code> for
     * property <code>p</code>. <code>o</code> is interpreted as
     * a typed literal with the appropriate RDF type.
    '''
    # param Property p, double o
    # result boolean
    # @abstractmethod
    # def hasLiteral(self, p, o):
    #     pass

    '''
     * Answer true iff this resource has the value <code>o</code> for
     * property <code>p</code>. <code>o</code> is interpreted as
     * a typed literal with the appropriate RDF type.
    '''
    # param Property p, float o
    # result boolean
    # @abstractmethod
    # def hasLiteral(self, p, o):
    #     pass

    '''
     * Answer true iff this resource has the value <code>o</code> for
     * property <code>p</code>. <code>o</code> is interpreted as
     * a typed literal with the appropriate RDF type.
    '''
    # param Property p, Object o
    # result boolean
    # @abstractmethod
    # def hasLiteral(self, p, o):
    #     pass

    '''
     * Test if this resource has a given property with a given value.
     *
     * @param p The property sought.
     * @param o The value of the property sought.
     * @return true if and only if this resource has property p with
     * value o.
    '''
    # param Property p, String o
    # result boolean
    # @abstractmethod
    # def hasProperty(self, p, o):
    #     pass

    '''
     * Test if this resource has a given property with a given value.
     *
     * @param p The property sought.
     * @param o The value of the property sought.
     * @param l The language of the property sought.
     * @return true if and only if this resource has property p with
     * value o.
    '''
    # param Property p, String o, String l
    # result boolean
    # @abstractmethod
    # def hasProperty(self, p, o, l):
    #     pass

    '''
     * Test if this resource has a given property with a given value.
     *
     * @param p The property sought.
     * @param o The value of the property sought.
     * @return true if and only if this resource has property p with
     * value o.
    '''
    # param Property p, RDFNode o
    # result boolean
    # @abstractmethod
    # def hasProperty(self, p, o):
    #     pass

    '''
     * Delete all the properties for this resource from the associated model.
     *
     * @return This resource to permit cascading.
    '''
    # param 
    # result Resource
    @abstractmethod
    def removeProperties(self):
        pass

    '''
     * Delete all the statements with predicate <code>p</code> for this resource
     * from its associated model.
     *
     * @param p the property to remove
     * @return this resource, to permit cascading
    '''
    # param Property p
    # result Resource
    @abstractmethod
    def removeAll(self, p):
        pass

    '''
     * Begin a transaction in the associated model.
     *
     * @return This resource to permit cascading.
    '''
    # param 
    # result Resource
    # @abstractmethod
    # def begin(self):
    #     pass

    '''
     * Abort the  transaction in the associated model.
     *
     * @return This resource to permit cascading.
    '''
    # param 
    # result Resource
    # @abstractmethod
    # def abort(self):
    #     pass

    '''
     * Commit the transaction in the associated model.
     *
     * @return This resource to permit cascading.
    '''
    # param 
    # result Resource
    # @abstractmethod
    # def commit(self):
    #     pass

    '''
     * Answer some resource R for which this.hasProperty( p, R ),
     * or null if no such R exists.
    '''
    # param Property p
    # result Resource
    @abstractmethod
    def getPropertyResourceValue(self, p):
        pass

